commonlibsse_ng\re\n/
NiTransform.rs

1use crate::re::NiMatrix3::NiMatrix3;
2use crate::re::NiPoint3::NiPoint3;
3
4/// Represents a 3D transformation with rotation, translation, and scale.
5#[repr(C)]
6#[derive(Debug, Clone, Copy, PartialEq)]
7pub struct NiTransform {
8    pub rotate: NiMatrix3,
9    pub translate: NiPoint3,
10    pub scale: f32,
11}
12
13impl NiTransform {
14    /// Creates a new identity transform.
15    #[inline]
16    pub const fn new() -> Self {
17        Self { rotate: NiMatrix3::new(), translate: NiPoint3::zero(), scale: 1.0 }
18    }
19
20    /// Inverts the transform.
21    pub fn invert(&self) -> Self {
22        let inv_scale = 1.0 / self.scale;
23        let inv_rotate = self.rotate.transpose();
24        let inv_translate = (inv_rotate * -self.translate) * inv_scale;
25
26        Self { rotate: inv_rotate, translate: inv_translate, scale: inv_scale }
27    }
28
29    /// Multiplies two transformations together.
30    #[inline]
31    pub fn mul_transform(&self, rhs: &Self) -> Self {
32        Self {
33            scale: self.scale * rhs.scale,
34            rotate: self.rotate * rhs.rotate,
35            translate: self.translate + (self.rotate * rhs.translate) * self.scale,
36        }
37    }
38
39    /// Transforms a point by the transform.
40    #[inline]
41    pub fn mul_point(&self, point: &NiPoint3) -> NiPoint3 {
42        ((self.rotate * *point) * self.scale) + self.translate
43    }
44}
45
46impl Default for NiTransform {
47    #[inline]
48    fn default() -> Self {
49        Self::new()
50    }
51}
52
53impl core::ops::Mul for NiTransform {
54    type Output = Self;
55
56    #[inline]
57    fn mul(self, rhs: Self) -> Self::Output {
58        self.mul_transform(&rhs)
59    }
60}
61
62impl core::ops::Mul<NiPoint3> for NiTransform {
63    type Output = NiPoint3;
64
65    #[inline]
66    fn mul(self, rhs: NiPoint3) -> Self::Output {
67        self.mul_point(&rhs)
68    }
69}
70
71#[cfg(test)]
72mod tests {
73    use super::*;
74
75    #[test]
76    fn test_invert_transform() {
77        let transform = NiTransform {
78            rotate: NiMatrix3::new(),
79            translate: NiPoint3::new(1.0, 2.0, 3.0),
80            scale: 2.0,
81        };
82
83        let inverted = transform.invert();
84        let expected = NiTransform {
85            rotate: NiMatrix3 { entry: [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]] },
86            translate: NiPoint3 { x: -0.5, y: -1.0, z: -1.5 },
87            scale: 0.5,
88        };
89        assert_eq!(inverted, expected);
90    }
91
92    #[test]
93    fn test_mul_transform() {
94        let t1 = NiTransform {
95            rotate: NiMatrix3::new(),
96            translate: NiPoint3::new(1.0, 2.0, 3.0),
97            scale: 2.0,
98        };
99
100        let t2 = NiTransform {
101            rotate: NiMatrix3::new(),
102            translate: NiPoint3::new(4.0, 5.0, 6.0),
103            scale: 3.0,
104        };
105
106        let result = t1 * t2;
107        let expected = NiTransform {
108            rotate: NiMatrix3::new(),
109            translate: NiPoint3::new(9.0, 12.0, 15.0),
110            scale: 6.0,
111        };
112
113        assert_eq!(result, expected);
114    }
115
116    #[test]
117    fn test_mul_point() {
118        let transform = NiTransform {
119            rotate: NiMatrix3::new(),
120            translate: NiPoint3::new(1.0, 2.0, 3.0),
121            scale: 2.0,
122        };
123
124        let point = NiPoint3::new(1.0, 1.0, 1.0);
125        let result = transform * point;
126        assert_eq!(result, NiPoint3::new(3.0, 4.0, 5.0));
127    }
128}